#include <string.h>
#include <sys/stat.h>

#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/system.h>

struct m_inode inode_table[NR_INODE]={{0, }, };

static void read_inode(struct m_inode *inode);

static int _bmap(struct m_inode *inode, int block, int create)
{
    struct buffer_head *bh;
    int i;

    if (block < 0)
        panic("_bmap: block < 0");
    if (block >= 7 + 512 + 512 * 512)   // 7个直接 + 1个一级间接 + 1个二级间接
        panic("_bmap: block > big");
    
    // 直接
    if (block < 7) {
        return inode->i_zone[block];
    }

    // 一级间接
    block -= 7;
    if (block < 512) {
        if (!inode->i_zone[7])
            return 0;
        bh = bread(inode->i_dev, inode->i_zone[7]);
        if (!bh)
            return 0;
        i = ((unsigned short *)(bh->b_data))[block];
        brelse(bh);
        return i;
    }

    // 二级间接
    block -= 512;
    if (!inode->i_zone[8])
        return 0;
    
    bh = bread(inode->i_dev, inode->i_zone[8]);
    if (!bh)
        return 0;
    i = ((unsigned short *)bh->b_data)[block >> 9];
    brelse(bh);
    if (!i)
        return 0;
    
    bh = bread(inode->i_dev, i);
    if (!bh)
        return 0;
    i = ((unsigned short *)bh->b_data)[block & 511];
    brelse(bh);
    return i;
}

int bmap(struct m_inode *inode, int block)
{
    return _bmap(inode, block, 0);
}

void iput(struct m_inode *inode)
{
    if (!inode)
        return;
    if (!inode->i_count)
        panic("iput: trying to free free inode");
    inode->i_count--;
}

struct m_inode *get_empty_inode(void)
{
    struct m_inode *inode;
    static struct m_inode *last_inode = inode_table;
    int i;

    do {
        inode = NULL;
        // 遍历查找未使用的结构体
        for (i = NR_INODE; i; i--) {
            if (++last_inode >= inode_table + NR_INODE)
                last_inode = inode_table;
            if (!last_inode->i_count) {
                inode = last_inode;
                break;
            }
        }
        // 如果结构体都被使用了
        if (!inode) {
            for (i = 0; i < NR_INODE; i++)
                printk("%04x: %6d\t", inode_table[i].i_dev, 
                    inode_table[i].i_num);
            panic("No free inodes in mem");
        }
    } while (inode->i_count);
    memset(inode, 0, sizeof(*inode));
    inode->i_count = 1;
    return inode;
}

struct m_inode *iget(int dev, int nr)
{
    struct m_inode *inode, *empty;

    if (!dev)
        panic("iget with dev == 0");
    inode = inode_table;
    // 查看inode是否已被读入
    while (inode < NR_INODE + inode_table) {
        if (inode->i_dev != dev || inode->i_num != nr) {
            inode++;
            continue;
        }
        inode->i_count++;
        return inode;
    }
    // 查找一个未被使用的inode结构体
    empty = get_empty_inode();
    if (!empty)
        return NULL;
    inode = empty;
    inode->i_dev = dev;
    inode->i_num = nr;
    read_inode(inode);  // 将数据读到这个结构体中
    return inode;
}

static void read_inode(struct m_inode *inode)
{
    struct super_block *sb;
    struct buffer_head *bh;
    int block;

    sb = get_super(inode->i_dev);
    block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks + (inode->i_num - 1) / INODES_PER_BLOCK;  // 计算inode所在的逻辑块
    bh = bread(inode->i_dev, block);
    if (!bh)
        panic("unable to read i-node block");
    __asm__("cld"::);
    *(struct d_inode *)inode = ((struct d_inode *)bh->b_data)[(inode->i_num - 1) % INODES_PER_BLOCK];
    brelse(bh);
}